package com.ruixiang.study.proxy;

import org.junit.Test;

import java.lang.reflect.*;

/**
 * @author ruixinag
 * @description
 * @create Created in 2022/1/21 14:48
 */
public class ProxyDemo1 {


    @Test
    public void test1() {
        Class<Calculator> calculatorClass = Calculator.class;

        //构造器
        Constructor<?>[] classConstructors = calculatorClass.getConstructors();
        // 方法信息
        Method[] calculatorClassMethods = calculatorClass.getMethods();
        System.out.println("-接口Class的构造器信息");
        printClassInfo(classConstructors);

        System.out.println("--接口Class的方法信息");
        printClassInfo(calculatorClassMethods);


        // 实现类对象
        Class<CalculatorImpl> calculatorImplClass = CalculatorImpl.class;
        Constructor<?>[] calculatorImplClassConstructors = calculatorImplClass.getConstructors();
        Method[] calculatorImplClassMethods = calculatorImplClass.getMethods();

        // 打印信息
        System.out.println("---实现类构造器");
        printClassInfo(calculatorImplClassConstructors);
        System.out.println("-- 实现类方法信息");
        printClassInfo(calculatorImplClassMethods);

    }


    /*

     * @return void
     * @describe  动态代理生产代理对象
     * @author ruixiang
     * @date 2022/1/21 15:02
     */
    @Test
    public void test2() {

        Class<?> proxyClass = Proxy.getProxyClass(CalculatorImpl.class.getClassLoader(), Calculator.class);
        Constructor<?>[] classConstructors = proxyClass.getConstructors();
        Method[] methods = proxyClass.getMethods();

        System.out.println("---打印代理类构造信息");
        printClassInfo(classConstructors);
        System.out.println("--打印代理类方法信息");
        printClassInfo(methods);


        // 实现类对象
        Class<CalculatorImpl> calculatorImplClass = CalculatorImpl.class;
        Constructor<?>[] calculatorImplClassConstructors = calculatorImplClass.getConstructors();
        Method[] calculatorImplClassMethods = calculatorImplClass.getMethods();

        // 打印信息
        System.out.println("---实现类构造器");
        printClassInfo(calculatorImplClassConstructors);
        System.out.println("-- 实现类方法信息");
        printClassInfo(calculatorImplClassMethods);

    }

    @Test
    public void test3() throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
        Class<?> proxyClass = Proxy.getProxyClass(Calculator.class.getClassLoader(), Calculator.class);
        Constructor<?> constructor = proxyClass.getConstructor(InvocationHandler.class);
        Calculator calculatorProxy = (Calculator) constructor.newInstance(new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                return 6666;
            }
        });

        System.out.println(calculatorProxy.subtract(1, 2));
    }

    /**
     * @return void
     * @description  动态代理生成对象
     * @author ruixiang
     * @date 2022/1/21 15:34
     */
    @Test
    public void test4() {
        CalculatorImpl target = new CalculatorImpl();
        // 获取增强的invocationHandler对象
        InvocationHandler handler = getInvocationHandler(target);
        Calculator proxyInstance = (Calculator) Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), handler);
        int add = proxyInstance.add(1, 2);
        System.out.println("add = " + add);
        int subtract = proxyInstance.subtract(2, 1);
        System.out.println("subtract = " + subtract);
    }

    /**
     * @return java.lang.reflect.InvocationHandler
     * @describe 生成增强对象
     * @author ruixiang
     * @date 2022/1/21 15:35
     */
    private InvocationHandler getInvocationHandler(final CalculatorImpl target) {
        return new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                System.out.println(method.getName() + "方法开始执行");
                Object result = method.invoke(target, args);
                System.out.println(method.getName() + "方法执行完毕");
                return result;
            }
        };

    }

    public void printClassInfo(Executable[] targets) {
        for (Executable target : targets) {
            //构造器方法
            String name = target.getName();
            StringBuilder stringBuilder = new StringBuilder(name);
            // 左括号
            stringBuilder.append("(");
            Class<?>[] parameterTypes = target.getParameterTypes();
            // 拼接参数
            for (Class<?> parameterType : parameterTypes) {

                stringBuilder.append(parameterType.getName()).append(",");
            }
            // 删除最后一个参数的逗号
            if (parameterTypes.length != 0) {
                stringBuilder.deleteCharAt(stringBuilder.length() - 1);
            }

            // 拼接右括号
            stringBuilder.append(")");
            System.out.println(stringBuilder.toString());
        }
    }

}
